package loader
{
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Rectangle;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.utils.Timer;
	
	[SWF(width="1253", height="643", backgroundColor="0x000000")]
	public class Preloader extends Sprite
	{
		/** 尝试重新加载资源的间隔 **/
		private static const RETRY_LOAD_INTERVAL:int = 3;
		
		/** 尝试重新加载同一资源的次数 **/
		private static const RETRY_LOAD_TIMES:int = 3;
		
		/** 当前资源加载失败次数 **/
		private  var failLoadTime:int = 0;
		
		/** 用于资源重新加载的计时器 **/
		private var reloadTimer:Timer;
		
		/** 主程序配置表的路径 **/
		private static const MAIN_FILE_CONFIG:String = "config/preload.xml";
		
		/** 背景图片 **/
		[Embed(source="../asset/pic/ui/load_bg.jpg")]
		private var LoadBg:Class;
		
		/** 进度条前景图片 **/
		[Embed(source="../asset/pic/ui/load_bar.png")]
		private var LoadBar:Class;

		/** 进度条图片 **/
		private var m_barBmp:Bitmap;
		
		/** 进度条宽度 **/
		private var m_barWidth:int;
		
		/** 信息文本 **/
		private var m_infoTxt:TextField;
		
		/** 资源加载信息的列表 **/
		private var loadList:Array = [];
		
		/** 当前资源加载的步骤 **/
		//private	var loadStep:int = -1;
		
	
		public function Preloader()
		{
			super();
			
			addEventListener( Event.ADDED_TO_STAGE, onAddedToStageHandler );
			
		}
		
		private function onAddedToStageHandler( e:Event ):void
		{
			configUI();
			
			loadConfig();
		}
		
		private function configUI():void
		{
			var bg:Bitmap = new LoadBg();
			
			bg.x = ( stage.stageWidth - bg.width ) / 2;
			
			bg.y = ( stage.stageHeight - bg.height ) / 2;
			
			addChild( bg );
			
			m_barBmp = new LoadBar();
			
			m_barBmp.x = bg.x + 275;
			
			m_barBmp.y = bg.y + 346;
			
			m_barWidth = m_barBmp.width;
			
			setProccessBar( 0 );
			
			addChild( m_barBmp );
			
			m_infoTxt = new TextField();
			m_infoTxt.defaultTextFormat = new TextFormat( null, 12, 0xfea904, true, null, null, null, null, "center" );
			m_infoTxt.filters = [ new GlowFilter(0x000000, 1, 2, 2, 10 ) ];
			m_infoTxt.width = m_barWidth;
			m_infoTxt.x = m_barBmp.x;
			m_infoTxt.y = m_barBmp.y + 30;
			m_infoTxt.text = "正在努力加载.....";
			
			addChild( m_infoTxt );
			
		}
		
		private function loadConfig():void
		{
			registerLoader( "配置文件", loadMainFile, URLLoader, MAIN_FILE_CONFIG + "?v=" + new Date().getMilliseconds() );
			
			//读取配置文件
			loadNext();
		}
		
		private function loadMainFile( loader:Object ):void
		{
			var urlLoader:URLLoader = loader as URLLoader;
			
			var xmlData:XML = new XML( urlLoader.data );
			
			var mainFileURL:String = xmlData.file + "?v=" + xmlData.version;
			
			registerLoader( "主程序", initMainFile, Loader, mainFileURL );
			
			loadNext();
			
		}
		
		private function initMainFile( loader:Object ):void
		{
			var len:int = numChildren;
			
			for( var i:int = 0; i < len; i++ )
			{
				removeChildAt( 0 );
			}
			
			m_infoTxt = null;
			
			m_barBmp = null;
			
			addChild( Loader( loader ) );
		}
		
		private function registerLoader( loaderName:String, completeHandler:Function, loaderClass:Class, url:String ):void
		{
			var loadInfo:Object = {};
			
			loadInfo.name = loaderName;
			
			loadInfo.complete = completeHandler;
			
			var loaderObj:Object;
			
			if( loaderClass == URLLoader )
			{
				loaderObj = new URLLoader();
				
				loadInfo.loadDispatcher = loaderObj;
			}
			else if( loaderClass == Loader )
			{
				loaderObj = new Loader();
				
				loadInfo.loadDispatcher = Loader( loaderObj ).contentLoaderInfo;
			}
			else
			{
				throw new Error( "Loader Type unsupported!!!" );
			}
			
			loadInfo.loader = loaderObj;
			
			loadInfo.url = new URLRequest( url );
			
			if( !loadList )
			{
				loadList = [];
			}
			
			loadList.push( loadInfo );
			
		}
		
		
		private function loadNext():void
		{
			if( loadList.length == 0 ) return;
			
			var loadInfo:Object = getLoadInfo();
			
			var loadDispatcher:Object = loadInfo.loadDispatcher;
			
			loadDispatcher.addEventListener( ProgressEvent.PROGRESS, onProgressHandler );
			
			loadDispatcher.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurityErrorHandler );
			
			loadDispatcher.addEventListener( IOErrorEvent.IO_ERROR, onErrorHandler );
			
			loadDispatcher.addEventListener( Event.COMPLETE, onCompleteHandler );  
			
			var urlRequest:URLRequest = loadInfo.url;
			
			loadInfo.loader.load( urlRequest );
			
			setProccessBar( 0 );
		
		}
		
		private function reloadLater():void
		{
			var loadInfo:Object =  getLoadInfo();
			
			if( loadInfo.loader is Loader )
			{
				loadInfo.loader.unload();
			}
			
			if( !reloadTimer )
			{
				reloadTimer = new Timer( RETRY_LOAD_INTERVAL * 1000, 1 );
			}
			
			reloadTimer.addEventListener( TimerEvent.TIMER_COMPLETE, reload );
			
			reloadTimer.reset();
			
			reloadTimer.start();
			
			setProccessBar( 0 );
			
		}
		
		private function reload( e:TimerEvent ):void
		{
			var loadInfo:Object =  getLoadInfo();
			
			m_infoTxt.text  = "尝试重新加载" +　loadInfo.name;
			
			loadInfo.loader.load( loadInfo.url );
			
		}
		
		private function onProgressHandler( e:ProgressEvent ):void
		{
			var loadInfo:Object = getLoadInfo();
			
			var percent:int =  Math.floor( ( e.bytesLoaded / e.bytesLoaded ) * 100 );
			
			setProccessBar( percent );
			
			m_infoTxt.text = "正在加载" + loadInfo.name + "  " + percent + "%" ;
			
		}
		
		private function onCompleteHandler( e:Event ):void
		{
			var loadInfo:Object = getLoadInfo();
			
			m_infoTxt.text = loadInfo.name + "加载完成!";
			
			var loadDispatcher:Object = loadInfo.loadDispatcher;
			
			loadDispatcher.removeEventListener( ProgressEvent.PROGRESS, onProgressHandler );
			
			loadDispatcher.removeEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurityErrorHandler );
			
			loadDispatcher.removeEventListener( IOErrorEvent.IO_ERROR, onErrorHandler );
			
			loadDispatcher.removeEventListener( Event.COMPLETE, onCompleteHandler ); 
			
			//释放掉
			loadList.shift();
			
			if( loadInfo.complete is Function ) 
			{
				loadInfo.complete( loadInfo.loader );
			}
		}
		
		private function onErrorHandler( e:IOErrorEvent ):void
		{
			var loadInfo:Object = getLoadInfo();
			
			if( failLoadTime < RETRY_LOAD_TIMES )
			{
				failLoadTime++;
			
				m_infoTxt.text  = loadInfo.name + "加载失败," + RETRY_LOAD_INTERVAL + "秒后重试.";
			
				reloadLater();
			}
			else
			{
				m_infoTxt.text  = loadInfo.name + "加载失败.";
			}
		}
		
		private function onSecurityErrorHandler( e:SecurityError ):void
		{
			var loadInfo:Object = getLoadInfo();
			
			m_infoTxt.text  =  loadInfo.name  + "加载错误, 请联系游戏客服人员.";
		}
		
		private function getLoadInfo():Object
		{
			var loadInfo:Object = loadList[ 0 ];
			
			if( !loadInfo )
			{
				throw new Error( "读取程序错误!!!" );
			}
			return loadInfo;
		}
		
		private function setProccessBar( percent:int ):void
		{
			m_barBmp.scrollRect = new Rectangle( 0, 0, m_barWidth * percent / 100, m_barBmp.height );
		}
	}
}